package com.guge.sports.toolPackage.utils;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.guge.sports.service.impl.StDeptServiceImpl;
import com.guge.sports.toolPackage.base.BaseService;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;


//ApplicationObjectSupport
//ApplicationContextAware
@Component("ApplicationContextUtils")
public final class ApplicationContextUtils implements ApplicationContextAware, ServletContextListener {


    //spring容器
    private static ApplicationContext rootApp;

    //子容器，spring-mvc
//    private static ApplicationContext webApp;

    private static ServletContext servletContext;

    private static Class entityCls;

    public static ApplicationContext getApp() {
        return rootApp;
    }

    public static Class getEntityCls() {
        return entityCls;
    }


    public static BaseService getServiceByGenericType(Class cls) {
        if (rootApp == null) {
            throw new NullPointerException("spring容器获取失败");
        }
        Map<String, BaseService> baseMapperMap = rootApp.getBeansOfType(BaseService.class);
        Collection<BaseService> services = baseMapperMap.values();
        for (BaseService service : services) {

           /* if (service instanceof StDeptServiceImpl) {
                System.out.println("1111111");
            }*/

            Class serviceClass = service.getClass();
            if (AopUtils.isCglibProxy(service)) {
                //如果是cglib代理
                serviceClass = serviceClass.getSuperclass();

               // Proxy.isProxyClass(serviceClass);
            }


            //System.out.println(service);

            //获取父类泛型
            ParameterizedType genericSuperclass = (ParameterizedType) serviceClass.getGenericSuperclass();
            //System.out.println(superclass.getName());
            //ParameterizedType genericSuperclass = (ParameterizedType) superclass.getGenericInterfaces()[0];

            //取第一个泛型
            Class genericType = (Class) genericSuperclass.getActualTypeArguments()[0];
            // System.out.println(genericSuperclass);
            //System.out.println(genericType.getSimpleName());

            //获取自身的泛型
            Class selfGenericType = getSelfGenericType(cls);

            if (genericType == selfGenericType) {
                entityCls = selfGenericType;
                //System.out.println("返回值service：" + service);
                return service;
            }
        }
        return null;
    }

    //监听器回调
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        this.servletContext = sce.getServletContext();
    }


    /**
     * 获取servletContext
     *
     * @return
     */
    public static ServletContext getServletContext() {
        return servletContext;
    }


    /**
     * 通过判断mapper泛型得到mapper
     */
    public static BaseMapper getMapperByGenericType(Class cls) {
        //System.out.println("进入方法");
        if (rootApp == null) {
            throw new NullPointerException("spring容器获取失败");
        }
        Map<String, BaseMapper> baseMapperMap = rootApp.getBeansOfType(BaseMapper.class);
        Collection<BaseMapper> mappers = baseMapperMap.values();
        for (BaseMapper mapper : mappers) {
            //System.out.println(mapper);
            Class superclass = mapper.getClass().getInterfaces()[0];
            //System.out.println(superclass.getName());
            ParameterizedType genericSuperclass = (ParameterizedType) superclass.getGenericInterfaces()[0];
            Class genericType = (Class) genericSuperclass.getActualTypeArguments()[0];
            //System.out.println(genericSuperclass);
            //System.out.println(genericType.getSimpleName());
            Class selfGenericType = getSelfGenericType(cls);
            if (genericType == selfGenericType) {
                entityCls = selfGenericType;
                //System.out.println("返回值mapper：" + mapper);
                return mapper;
            }
        }
        return null;
    }


    /**
     * 得到自身的泛型
     *
     * @return
     */
    public static Class getSelfGenericType(Class cls) {

        if (AopUtils.isCglibProxy(cls)) {
            //如果是cglib代理
            cls = cls.getSuperclass();
        }
        Type genericSuperclass = cls.getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
            //System.out.println(genericSuperclass);
            Class selfGenericType = (Class) parameterizedType.getActualTypeArguments()[0];
            //System.out.println(selfGenericType.getSimpleName());
            return selfGenericType;
        } else {
            return null;
        }

    }


    //实现ApplicationContextAware接口，重写方法
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //System.out.println("获取容器--------");
        //获取spring容器
        rootApp = applicationContext;

    }


    public static Object getBean(String beanName) {
        return rootApp.getBean(beanName);
    }

    public static <T> T getBean(String beanName, Class<T> clazz) {
        return rootApp.getBean(beanName, clazz);
    }

    public static <T> T getBean(Class<T> clazz) {
        return rootApp.getBean(clazz);
    }


}
